﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CommServer.Common.Database;
using Dapper;
using System.Threading;
using System.IO;

namespace CommServer.Upgrade
{
    public class upgradeMng
    {
        private Dictionary<string, upgradeDevice> updateList;
        private List<int> upgradeHours = new List<int>();
        private Thread workThread;
        private bool stopUpgrade = false;
        private string Path;
        public bool StopUpgrade { get => stopUpgrade; set => stopUpgrade = value; }
        private Dictionary<string, upgradeDevice> failureList;
        public upgradeMng()
        {
            updateList = new Dictionary<string, upgradeDevice>();
            failureList = new Dictionary<string, upgradeDevice>();
            Path = Directory.GetCurrentDirectory() + @"\wwwroot\DevImage\";
            if (!Directory.Exists(Path))
            {
                Directory.CreateDirectory(Path);
            }
        }
        ~upgradeMng()
        {
            stopUpgrade = true;
        }
        public void start()
        {
            workThread = new Thread(new ThreadStart(startUpgrade));
            workThread.Start();
        }
        public void stop()
        {
            if ((workThread != null) && (workThread.IsAlive))
            {
                stopUpgrade = true;
            }
        }
        private void startUpgrade()
        {
            while (true)
            {
                Thread.Sleep(1000);
                if (stopUpgrade)
                    break;
                if (DateTime.Now.Hour == 0)
                {
                    if (upgradeHours.Count == 0)
                    {
                        upgradeHours.Add(8);
                        upgradeHours.Add(16);
                    }
                }
                int hour = DateTime.Now.Hour;
                if (upgradeHours.Contains(hour))
                {
                    upgradeHours.Remove(hour);
                    getUpdateList();
                    upgradeDo();
                }
            }
        }
        private void upgradeDo()
        {
            int count = updateList.Count;
            while (count > 0)
            {
                List<string> Keys = updateList.Keys.ToList();
                for (int i = Keys.Count - 1; i >= 0; i--)
                {
                    if (Program.GetDeviceServer().isOnline(Keys[i]))
                    {
                        if ((!updateList[Keys[i]].Upgrading) && (!updateList[Keys[i]].Completed))
                        {
                            updateList[Keys[i]].onComplete += new Action<string, dynamic>(onUpgradeCompleted);
                            updateList[Keys[i]].startUpgrade(true);
                            updateList.Remove(Keys[i]);
                        }
                    }
                }
                count = updateList.Count;
            }
        }
        private void onUpgradeCompleted(string rtuSN, dynamic state)
        {
            using (var conn = DbHelper.GetConn())
            {
                string strsql = "update  programrtu set upgradedate=now(), upgradestatus = " + (state.success ? 1 : 2).ToString() + "upgradememo='" + state.errMsg + "' where programid= " + state.obj.ProgramId.ToString() + " and RtuSn='" + rtuSN + "'";
                conn.Execute(strsql);

            }
        }
        private void getUpdateList()
        {
            string strsql = @"select a.programId,a.version,a.filename, b.RtuSn,b.upgradestatus from programinfo A ,programrtu B
                            where a.programId = b.programid
                            and a.valid = 1
                            and b.upgradestatus = 0 ";
            using (var conn = DbHelper.GetConn())
            {
                var rows = conn.Query(strsql);
                if (rows == null)
                    return;
                foreach (dynamic row in rows)
                {
                    upgradeDevice device = new upgradeDevice(row.RtuSn, Path + row.filename);
                    device.Version = row.version;
                    device.Upgrading = false;
                    device.Completed = false;
                    device.ProgramId = row.programId;
                    updateList.Add(row.RtuSn, device);
                }
            }
        }

    }
}
